home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr22 / startd22.zip / STARTD22.C < prev    next >
Text File  |  1993-06-05  |  19KB  |  507 lines

  1. /*
  2.  *  STARTD:  A simple program to start a DOS session under OS/2 2.0.
  3.  *           This program can be run from an OS/2 command prompt
  4.  *
  5.  *  Last Modfied: 07/07/92
  6.  *
  7.  *  Author: Norm Ross
  8.  *          Jim Sauber
  9.  *
  10.  *  Using the example code for BOOTA.C found in IBM DOCUMENT GBOF-2254
  11.  *
  12.  *  This was written mainly to provide access to DOS SETTINGS for
  13.  *  VDM sessions. Since I have disabled the WPS to free up the space,
  14.  *  I can't specify DOS settings for my favorite DOS apps.
  15.  *  STARTD is not meant to replace START but it does many of
  16.  *  the same things...
  17.  *
  18.  *  If you change this program and re-distribute it please leave this
  19.  *  header intact and send the readme file with it.
  20.  *
  21.  *  MODIFICATION HISTORY
  22.  *
  23.  *  07-Jul-1992  Norm Ross, npross@undergrad.uwaterloo.ca
  24.  *     1.00 : Initial version
  25.  *  25-Feb-1993  Jim Sauber
  26.  *     2.00 : Handles the creation of asynchronous DOS sessions
  27.  *     2.10 : Binds the parent to the child and handles icon started apps
  28.  *  06-Jun-1993  Jim Sauber
  29.  *     2.20 : Increased size of Environment to 4K and resolved OS/2 2.1 problems
  30.  */
  31.  
  32. #define INCL_DOSSESMGR
  33. #define INCL_DOSMISC
  34. #define INCL_DOSPROCESS
  35. #define INCL_WIN
  36. #define INCL_DOSMEMMGR
  37. #define INCL_WINSWITCHLIST
  38. #include <os2.h>
  39. #include <stdio.h>
  40. #include <io.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43.  
  44. #include "pidinfo.h"
  45. #define PID_BUFFER_SIZE     0x8000
  46. #define DOS_PROGRAM_IDENT   "SYSINIT" // Identifies a DOS program
  47. #define WAIT_HOLD_TIME      5000      // Amount of time between checking for
  48.                                       // child process existence
  49.  
  50. PBYTE readEnv(PSZ pFileName);
  51. void  ChildProcess (PID) ;
  52.  
  53. PSZ pBootFailure = "Session could not be started.\r\n";
  54. char szPgmInputs[512];
  55. char szDosPgmInputs[512];
  56.  
  57. STARTDATA startd;                  /* Session start information */
  58. ULONG ChildSessionID;              /* Session and Process ID for new session*/
  59. PID pidChildPid;
  60. char fDebug ;                      /* flag whether to dump debug info */
  61.  
  62.  
  63. void main(int argc, char *argv[])
  64.   {
  65.   USHORT       rc, i ;
  66.   USHORT       flagWin = 0, flagFs = 0, flagKeep = 0, flagNoCmd = 0;
  67.  
  68.   fDebug = FALSE ;
  69.  
  70.   /* ---- init startd struct defaults */
  71.   startd.Length                   = sizeof(STARTDATA);
  72.   startd.Related                  = SSF_RELATED_INDEPENDENT;
  73.   startd.FgBg                     = SSF_FGBG_FORE;
  74.   startd.TraceOpt                 = SSF_TRACEOPT_NONE;
  75.   startd.PgmTitle                 = NULL;
  76.   startd.PgmName                  = NULL;
  77.   startd.PgmInputs                = NULL;
  78.   startd.TermQ                    = NULL;
  79.   startd.Environment              = NULL;
  80.   startd.InheritOpt               = SSF_INHERTOPT_PARENT;
  81.   startd.SessionType              = SSF_TYPE_DEFAULT;
  82.   startd.PgmControl               = SSF_CONTROL_VISIBLE;
  83.  
  84.   /* ------ Process args */
  85.   while(--argc > 0)
  86.     {
  87.     char *arg;
  88.  
  89.     switch(**++argv)
  90.       {
  91.       case '\"':
  92.         startd.PgmTitle = strtok(*argv, "\"");
  93.         break;
  94.       case '-':
  95.       case '/':
  96.         arg = (*argv)+1;
  97.         if (strlen(arg) == 1)
  98.           {
  99.           switch(*arg)
  100.             {
  101.             case 'n':
  102.             case 'N': flagNoCmd = 1; break;
  103.             case 'k':
  104.             case 'K': flagKeep = 1; break;
  105.             case 'c':
  106.             case 'C': break;
  107.             case 'f':
  108.             case 'F': startd.FgBg = SSF_FGBG_FORE; break;
  109.             case 'B':
  110.             case 'b': startd.FgBg = SSF_FGBG_BACK; break;
  111.             case 'i':
  112.             case 'I': startd.InheritOpt = SSF_INHERTOPT_SHELL; break;
  113.             case '?': usage(); break;
  114.             default:
  115.               fprintf(stderr, "Unrecognized option: %s\n", arg);
  116.               usage();
  117.               break;
  118.             }
  119.           }
  120.           else if (stricmp(arg, "DOS") == 0)
  121.             startd.SessionType = SSF_TYPE_VDM;
  122.           else if (stricmp(arg, "WIN") == 0)
  123.             flagWin = 1;
  124.           else if (stricmp(arg, "WAIT") == 0)
  125.             startd.Related = SSF_RELATED_CHILD;
  126.           else if (stricmp(arg, "FS") == 0)
  127.             flagFs = 1;
  128.           else if (stricmp(arg, "FG") == 0)
  129.             startd.FgBg = SSF_FGBG_FORE;
  130.           else if (stricmp(arg, "BG") == 0)
  131.             startd.FgBg = SSF_FGBG_BACK;
  132.           else if (stricmp(arg, "MAX") == 0)
  133.             startd.PgmControl |= SSF_CONTROL_MAXIMIZE;
  134.           else if (stricmp(arg, "MIN") == 0)
  135.             startd.PgmControl |= SSF_CONTROL_MINIMIZE;
  136.           else if (stricmp(arg, "INV") == 0)
  137.             startd.PgmControl |= SSF_CONTROL_INVISIBLE;
  138.           else if (stricmp(arg, "PM") == 0)
  139.             startd.SessionType = SSF_TYPE_PM;
  140.           else if (strnicmp(arg, "pos", 3) == 0)
  141.             {
  142.             char *s = strtok(arg, "=");
  143.  
  144.             /* ---- I really should check strtok's return... */
  145.             startd.PgmControl |= SSF_CONTROL_SETPOS;
  146.             startd.InitXPos = atoi(strtok(NULL, ","));
  147.             startd.InitYPos = atoi(strtok(NULL, ","));
  148.             startd.InitXSize = atoi(strtok(NULL, ","));
  149.             startd.InitYSize = atoi(strtok(NULL, ""));
  150.             }
  151.           else if (stricmp(arg, "PGM") == 0)
  152.             {
  153.             char *p = szPgmInputs;
  154.             /* ---- strip quotes from name if there are any */
  155.             startd.PgmName = strtok(*argv, "\"");
  156.  
  157.             /* ---- cat the rest of the args together to pass to pgm */
  158.             while (argc > 1)
  159.               {
  160.               argc--;
  161.               argv++;
  162.               strcpy(p, *argv);
  163.               p += strlen(*argv);
  164.               *p++ = ' '; /* put spaces between the args */
  165.               }
  166.             *p = '\0';
  167.             startd.PgmInputs = szPgmInputs;
  168.             break;
  169.             }
  170.           else if (stricmp(arg, "ICON") == 0)
  171.             {
  172.             startd.IconFile = *++argv;
  173.             argc--;
  174.             }
  175.           else if (stricmp(arg, "SF") == 0)
  176.             {
  177.             char *fname = *++argv;
  178.             argc--;
  179. //            if (access(fname, 0))
  180. //              fprintf(stderr, "Session File %s not found\n", fname);
  181.             startd.Environment = readEnv(fname);
  182.             }
  183.           else if (stricmp(arg, "DEBUG") == 0)
  184.             fDebug = TRUE ;
  185.           else
  186.             {
  187.             printf("Unrecognized option: %s\n", arg);
  188.             usage();
  189.             }
  190.          break;
  191.  
  192.       default:
  193.         {
  194.         char *p = szPgmInputs;
  195.         startd.PgmName = *argv;
  196.         /* ---- cat the rest of the args together to pass to pgm */
  197.         while (argc > 1)
  198.           {
  199.           argc--;
  200.           argv++;
  201.           strcpy(p, *argv);
  202.           p += strlen(*argv);
  203.           *p++ = ' '; /* put spaces between the args */
  204.           }
  205.         *p = '\0';
  206.         startd.PgmInputs = szPgmInputs;
  207.         break;
  208.         }
  209.       } /* switch */
  210.   } /* while */
  211.  
  212.   /* ------ Start thru Command processor */
  213.   if ((startd.PgmName!=NULL)&&(startd.SessionType!=SSF_TYPE_PM)&&(!flagNoCmd))
  214.     {
  215.     if (flagKeep)
  216.       strcpy(szDosPgmInputs, "/k ");
  217.     else
  218.       strcpy(szDosPgmInputs, "/c ");
  219.     strcat(szDosPgmInputs, startd.PgmName);
  220.     strcat(szDosPgmInputs, " ");
  221.     strcat(szDosPgmInputs, startd.PgmInputs);
  222.     startd.PgmInputs = szDosPgmInputs;
  223.     startd.PgmName = NULL;
  224.    }
  225.  
  226.   /* ------ Set the correct session type */
  227.   if (flagWin)
  228.     {
  229.     switch(startd.SessionType)
  230.       {
  231.       case SSF_TYPE_DEFAULT:
  232.         startd.SessionType = SSF_TYPE_WINDOWABLEVIO;
  233.         break;
  234.       case SSF_TYPE_VDM:
  235.         startd.SessionType = SSF_TYPE_WINDOWEDVDM;
  236.         break;
  237.       case SSF_TYPE_PM:
  238.         break;
  239.       } /* switch */
  240.     } /* if */
  241.   else if (flagFs)
  242.     {
  243.     switch(startd.SessionType)
  244.       {
  245.       case SSF_TYPE_DEFAULT: startd.SessionType = SSF_TYPE_FULLSCREEN; break;
  246.       case SSF_TYPE_VDM: break;
  247.       case SSF_TYPE_PM: break;
  248.       } /* switch */
  249.     } /* elseif */
  250.  
  251.   /* if debug is set, then dump all settings */
  252.   if (fDebug)
  253.     {
  254.     printf ("Related    = %d\n", startd.Related) ;
  255.     printf ("FgBg       = %d\n", startd.FgBg) ;
  256.     printf ("TraceOpt   = %d\n", startd.TraceOpt) ;
  257.     printf ("PgmTitle   = ") ;
  258.     if (startd.PgmTitle != NULL)
  259.       for (i = 0; startd.PgmTitle[i] != 0; ++i)
  260.         printf ("%c", startd.PgmTitle[i]) ;
  261.     printf ("\n") ;
  262.     printf ("PgmName    =") ;
  263.     if (startd.PgmName != NULL)
  264.       for (i = 0; startd.PgmName[i] != 0; ++i)
  265.         printf ("%c", startd.PgmName[i]) ;
  266.     printf ("\n") ;
  267.     printf ("PgmInputs  =") ;
  268.     if (startd.PgmInputs != NULL)
  269.       for (i = 0; startd.PgmInputs[i] != 0; ++i)
  270.         printf ("%c", startd.PgmInputs[i]) ;
  271.     printf ("\n") ;
  272.     printf ("TermQ      =") ;
  273.     if (startd.TermQ != NULL)
  274.       for (i = 0; startd.TermQ[i] != 0; ++i)
  275.         printf ("%c", startd.TermQ[i]) ;
  276.     printf ("\n") ;
  277.     printf ("Environment= ") ;
  278.     if (startd.Environment != NULL)
  279.       for (i = 0; startd.Environment[i] != 10; ++i)
  280.         printf ("%c", startd.Environment[i]) ;
  281.     printf ("\n") ;
  282.     printf ("InheritOpt = %d\n", startd.InheritOpt) ;
  283.     printf ("SessionType= %d\n", startd.SessionType) ;
  284.     printf ("PgmControl = %d\n", startd.PgmControl) ;
  285.     }
  286.  
  287.   /* ------ Start the Session */
  288.   rc = DosStartSession( &startd, &ChildSessionID, &pidChildPid );
  289.  
  290.   if(rc)
  291.     /* ------ Print out failure message */
  292.     DosPutMessage(1,strlen(pBootFailure),pBootFailure);
  293.   else if (startd.Related == SSF_RELATED_CHILD)
  294.     ChildProcess (pidChildPid) ;
  295.   return;
  296.   }
  297.  
  298. #define MAXENV 4096
  299. /************************************************************************/
  300. // Read the DOS environment file and create the environment string
  301. /************************************************************************/
  302. PBYTE readEnv(PSZ fname)
  303.   {
  304.   FILE *fptr;
  305.   PBYTE env = (PBYTE)malloc(MAXENV);
  306.   PBYTE p = env;
  307.   char *i ;
  308.  
  309.   fptr = fopen(fname, "rb");
  310.   if (fptr == (FILE *)NULL)
  311.     {
  312.     fprintf(stderr, "\nFile %s cannot be found\n");
  313.     exit(-1);
  314.     }
  315.  
  316.   // If the env flag is DOS_VERSION, then need to concatenate all the strings
  317.   // together to form 1 environment string. If only 0x0a terminates the input
  318.   // then remove the NULL, concatenate the 0x0a and the string and add a
  319.   // NULL
  320.   while (fgets(p, 80, fptr))
  321.     {
  322.     p+=strlen(p);
  323.     // if last 2 chars are crlf then remove them, if last char is lf, then
  324.     // keep it
  325.     if (*(p-2) == '\r' && *(p-1) == '\n')
  326.       {
  327.       *(p-2)='\0';
  328.       --p ;
  329.       } /* if */
  330. //    *(p-1)='\0';
  331.  
  332.     if (p>env + 4096)
  333.       {
  334.       fprintf(stderr, "ERROR: too many settings\n");
  335.       fflush(stderr);
  336.       exit(-1);
  337.       }
  338.     } /* while */
  339.   realloc(env, p-env);
  340.   fclose (fptr) ;
  341.   return(env);
  342.   }
  343.  
  344. /************************************************************************/
  345. // Display for the user the usage information
  346. /************************************************************************/
  347. usage( void )
  348.   {
  349.   fprintf(stderr, "STARTD VERSION 2.2 by Norm Ross & Jim Sauber Copyright (c) 1993\n\n");
  350.   fprintf(stderr, "startd [\"program title\"] [/BG /C /DOS /F /FS /I /ICON iconfile /INV /K /MAX\n\t /MIN /PGM POS=x,y,x1,y1 /SF settingsfile /WIN] [command ...]\n\n");
  351.   fprintf(stderr, "\t/B[G]\t start session in background\n");
  352.   fprintf(stderr, "\t/C\t close session upon completion\n");
  353.   fprintf(stderr, "\t/DOS\t start a dos session\n");
  354.   fprintf(stderr, "\t/F[G]\t start session in foreground\n");
  355.   fprintf(stderr, "\t/FS\t start a full screen session\n");
  356.   fprintf(stderr, "\t/I\t sets SSF_INHERTOPT_SHELL\n");
  357.   fprintf(stderr, "\t/ICON\t uses the specified icon file\n");
  358.   fprintf(stderr, "\t/INV\t start the application invisibly\n");
  359.   fprintf(stderr, "\t/K\t keep the session around after it is finished\n");
  360.   fprintf(stderr, "\t/MAX\t start maximized\n");
  361.   fprintf(stderr, "\t/MIN\t start minimized\n");
  362.   fprintf(stderr, "\t/N\t don't start indirectly through command processor\n");
  363.   fprintf(stderr, "\t/PGM\t the next argument is the program name\n");
  364.   fprintf(stderr, "\t/PM\t start a PM program\n");
  365.   fprintf(stderr, "\t/POS=x,y,x1,y1\t specify window position and size\n");
  366.   fprintf(stderr, "\t/SF\t read the specified dos settings file\n");
  367.   fprintf(stderr, "\t/WIN\t start a windowed session\n");
  368.   fprintf(stderr, "\t/WAIT\t doesn't work\n");
  369.   exit(1);
  370.   }
  371.  
  372. /************************************************************************/
  373. // Function: To start asynchronous process
  374. // The function searches the process list and switch list until it finds
  375. // an ancestor of the current process in the switch list. It then removes
  376. // that process from the switch list and if it is a window, minmizes it.
  377. /************************************************************************/
  378. void ChildProcess(PID pidChildPid)
  379.   {
  380.   USHORT       usActiveProcesses ;   /* count of active processes                     */
  381.   PBUFFHEADER  pbh ;                 /* buffer for task info                          */
  382.   PPROCESSINFO ppiLocal ;            /* child process info                            */
  383.   BOOL         fPidFound ;           /* flag whether child process is found           */
  384.   PTIB         pTib ;                /* Tib info of current process                   */
  385.   PPIB         pPib ;                /* Pib info of current process                   */
  386.   HAB          hab ;                 /* handle to switch list                         */
  387.   HSWITCH      hswitch ;             /* handle to switch entry                        */
  388.   ULONG        cbItems, cbBuf ;      /* sizeof of Process buffer                      */
  389.   PBYTE        pBase ;               /* pointer to memory                             */
  390.   PSWBLOCK     pswblk ;              /* pointer to allocated memory                   */
  391.   PSWENTRY     pSwitchEntry ;        /* pointer to each switch entry in list          */
  392.   SHORT        i ;                   /* misc counter                                  */
  393.   ULONG        ulCurrentType ;       /* current session type                          */
  394.   PID          pidParentPid ;        /* current process' immediate parent's PID       */
  395.   PID          pidCurrentPid ;       /* PID of this process                           */
  396.   PID          pidAncestorPid ;      /* PID of an ancestor in the switch list         */
  397.   HWND         hwndAncestorFrame ;   /* frame hwnd of the ancestor in the switch list */
  398.   HSWITCH      hAncestorSwitch ;     /* switch entry handle to displayed ancestor     */
  399.   SWCNTRL      swParentControl ;     /* switch entry info parent                      */
  400.   SWCNTRL      swAncestorControl ;   /* switch entry of ancestor                      */
  401.   STATUSDATA   sdSetSessionData ;    /* DosSetSession status data */
  402.   USHORT       rc ;                  /* misc return code                              */
  403.  
  404.   rc = DosGetInfoBlocks (&pTib, &pPib) ;
  405.   ulCurrentType = pPib->pib_ultype ;
  406.   pidCurrentPid= pPib->pib_ulpid ;
  407.   pidParentPid = pPib->pib_ulppid ;
  408.  
  409.   /* allocate memory for Process list */
  410.   rc = DosAllocMem((PPVOID) &pBase, (ULONG) 40000, PAG_READ | PAG_WRITE) ;
  411.   rc = DosSubSetMem (pBase, DOSSUB_INIT | DOSSUB_SPARSE_OBJ, 4000) ;
  412.  
  413.   /* get the process list */
  414.   pbh = malloc (PID_BUFFER_SIZE) ;
  415.   rc = DosQProcStatus (pbh, PID_BUFFER_SIZE) ;
  416.   ppiLocal = pbh->ppi ;
  417.  
  418.   /* get the switch list */
  419.   cbItems = WinQuerySwitchList (hab, NULL, 0) ;
  420.   cbBuf = (cbItems * sizeof(SWENTRY)) + sizeof(HSWITCH) ;
  421.   rc = DosSubAllocMem((PVOID) pBase, (PPVOID) &pswblk, (ULONG) cbBuf) ;
  422.   do
  423.     {
  424.     rc = WinQuerySwitchList (hab, pswblk, cbBuf) ;
  425.  
  426.     /* search the switch list to find an ancestor of the current process */
  427.     /* pidAncestorPid = -1 means no ancestor found yet */
  428.     pidAncestorPid = -1 ;
  429.     pSwitchEntry = &(pswblk->aswentry[0]) ;
  430.     for (i = 0; i < cbItems && pidAncestorPid == -1; ++i, ++pSwitchEntry)
  431.       {
  432.       hswitch = pSwitchEntry->hswitch ;
  433.       rc = WinQuerySwitchEntry (hswitch, &swParentControl) ;
  434.       /* if found current pid in the switch list */
  435.       if (pidCurrentPid == swParentControl.idProcess)
  436.         {
  437.         pidAncestorPid = swParentControl.idProcess ;
  438.         hwndAncestorFrame = swParentControl.hwnd ;
  439.         }
  440.       /* if found parent pid in the switch list */
  441.       if (pidParentPid == swParentControl.idProcess)
  442.         {
  443.         pidAncestorPid = swParentControl.idProcess ;
  444.         hwndAncestorFrame = swParentControl.hwnd ;
  445.         }
  446.       }
  447.  
  448.     /* if ancestor not found in the switch list this time, go back */
  449.     /* one more generation                                         */
  450.     if (pidAncestorPid == -1) {
  451.       fPidFound = FALSE ;
  452.       while(ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR && !fPidFound){
  453.         ++usActiveProcesses ;
  454.         if (ppiLocal->pid == pidParentPid)
  455.           {
  456.           fPidFound = TRUE ;
  457.           pidParentPid = ppiLocal->pidParent ;
  458.           } /* endif */
  459.         ppiLocal = (PPROCESSINFO) (ppiLocal->ptiFirst+ppiLocal->usThreadCount );
  460.       }
  461.     } else {
  462.     } /* endif */
  463.   } while ( pidAncestorPid == -1 && pidParentPid != 0); /* enddo */
  464.  
  465. //  hAncestorSwitch = WinQuerySwitchHandle (hwndAncestorFrame, 0) ;
  466. //  rc = WinQuerySwitchEntry (hswitch, &swAncestorControl) ;
  467. //  swAncestorControl.uchVisibility = SWL_INVISIBLE;
  468. //  swAncestorControl.fbJump = SWL_NOTJUMPABLE;
  469. //  WinChangeSwitchEntry (hAncestorSwitch, &swAncestorControl) ;
  470.   /* If this is a windowed session, minimize it */
  471.   if (ulCurrentType == 2)
  472.     rc = WinPostMsg (hwndAncestorFrame, WM_SYSCOMMAND,
  473.                      MPFROMSHORT(SC_MINIMIZE), NULL) ;
  474.  
  475.   /* Set so when the parent's icon is clicked, the child shows up */
  476.   sdSetSessionData.Length = 6 ;
  477.   sdSetSessionData.SelectInd = 2 ;
  478.   sdSetSessionData.BondInd = 1 ;
  479.   DosSetSession (ChildSessionID, &sdSetSessionData) ;
  480.  
  481.   /* Wait for child to finish */
  482.   do
  483.     {
  484.     DosSleep (WAIT_HOLD_TIME) ;
  485.     rc = DosQProcStatus (pbh, PID_BUFFER_SIZE) ;
  486.     ppiLocal = pbh->ppi ;
  487.     usActiveProcesses = 0 ;
  488.     fPidFound = FALSE ;
  489.     while(ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR && !fPidFound)
  490.       {
  491.       ++usActiveProcesses ;
  492.       if (ppiLocal->pid == pidChildPid)
  493.         fPidFound = TRUE ;
  494.       ppiLocal = (PPROCESSINFO) (ppiLocal->ptiFirst+ppiLocal->usThreadCount );
  495.       }
  496.     } while (fPidFound) ;
  497.  
  498.   swAncestorControl.uchVisibility = SWL_VISIBLE;
  499.   swAncestorControl.fbJump = SWL_JUMPABLE;
  500.   WinChangeSwitchEntry (hAncestorSwitch, &swAncestorControl) ;
  501.   if (ulCurrentType == 2)
  502.     rc = WinPostMsg (hwndAncestorFrame, WM_SYSCOMMAND,
  503.                      MPFROMSHORT(SC_RESTORE), NULL) ;
  504.   return ;
  505.   }
  506. 
  507.